package com.adcc.ags.cgw;

import com.adcc.ags.cgw.utils.FileUtil;
import com.google.common.base.Strings;
import com.ibm.mq.MQException;
import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.cli.EnvironmentCommand;
import io.dropwizard.setup.Environment;
import io.dropwizard.util.Generics;

import java.io.File;
import java.io.FileWriter;

import net.sourceforge.argparse4j.inf.Namespace;
import net.sourceforge.argparse4j.inf.Subparser;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ServerTraceCommand<T extends Configuration> extends EnvironmentCommand<T> {
    private static final Logger LOGGER = LoggerFactory.getLogger(ServerTraceCommand.class);

    private final Class<T> configurationClass;

    public ServerTraceCommand (Application<T> application) {
        this(application, "serverTrace", "Runs the Dropwizard application as an HTTP server and opens MQException trace");
    }

    private ServerTraceCommand(Application<T> application, String name, String description) {
        super(application, name, description);
        this.configurationClass = application.getConfigurationClass();
    }

    @Override
    protected  Class<T> getConfigurationClass() {
        return configurationClass;
    }

    @Override
    public void configure(Subparser subparser) {
        super.configure(subparser);
        subparser.addArgument("log")
                .nargs("?")
                .help("mqException log file");
        subparser.addArgument("logAppend")
                .type(boolean.class)
                .nargs("?")
                .help("mqException log is append or not");
    }

    @Override
    protected void run(Environment environment, Namespace namespace, T configuration) throws Exception {
        // MQException Log File
        final String logPath = namespace.getString("log");
        final boolean logAppend = namespace.getBoolean("logAppend") == null ? false : namespace.getBoolean("logAppend");

        if (!Strings.isNullOrEmpty(logPath)) {
            final File logFile = new File(logPath);
            if (!FileUtil.isExist(logFile.getParent())) {
                FileUtil.mkdir(logFile.getParent());
            }
            MQException.log = new FileWriter(logFile, logAppend);
        }

        // Server
        final Server server = configuration.getServerFactory().build(environment);
        try {
            server.addLifeCycleListener(new LifeCycleListener());
            cleanupAsynchronously();
            server.start();
        } catch (Exception e) {
            LOGGER.error("Unable to start server, shutting down", e);
            try {
                server.stop();
            } catch (Exception e1) {
                LOGGER.warn("Failure during stop server", e1);
            }
            try {
                cleanup();
            } catch (Exception e2) {
                LOGGER.warn("Failure during cleanup", e2);
            }
            throw e;
        }
    }

    private class LifeCycleListener extends AbstractLifeCycle.AbstractLifeCycleListener {

        @Override
        public void lifeCycleStopped(LifeCycle event) {
            cleanup();
        }
    }
}